<?php
if (! defined('IN_SITE')) {
	exit('invalid request');
}

include_once ROOT_PATH . '../smarty/Smarty.class.php';

/**
 * 定制功能：
 * 扫描模板中出现的 css 和 js 文件，如果符合特定的条件（以 /res/ 开头），则合并后统一引用。
 * css 合并后在 </head> 之前引用，js 合并后在 </body> 之前引用。
 *
 * 通过 MySmarty 渲染的模板，在引用 css 和 js 文件的时候，只需使用最简单的方式即可：
 * 		<link rel="stylesheet" type="text/css" href="/res/common.css">
 * 		<script type="text/javascript" src="/res/jquery-1.11.1.js"></script>
 * 不用写 CDN 前缀，也不用写版本号尾缀。
 */
class MySmarty extends Smarty {
	private $prefix;
	private $suffix;
	private $linked_res;

	public function __construct($cdn_prefix = '', $vstamp = '')
	{
		parent::__construct();
		$this->setTemplateDir(ROOT_PATH . 'templates/');
		$this->setCompileDir(ROOT_PATH . 'templates_c/');
		$this->setConfigDir(ROOT_PATH . '../smarty/configs/');
		$this->setCacheDir(ROOT_PATH . '../smarty/cache/');

		$this->prefix = $cdn_prefix;
		$this->suffix = empty($vstamp) ? '' : "?v={$vstamp}";
		$this->linked_res = array();

		if(isDebugStage()){
			$smarty->force_compile = false;
			$this->registerFilter('post', array($this, 'postFilter'));
			$this->registerFilter('output', array($this, 'outputFilter'));
		}else{
			$this->registerFilter('post', array($this, 'postFilter'));
			$this->registerFilter('output', array($this, 'outputFilter'));
		}
	}

	/**
	 * 在编译模板的时候，提取出模板中引用的 css 和 js，记录下来。
	 */
	function postFilter($tpl_source, Smarty_Internal_Template $template)
	{
		// 调试模式下不做文件合并
		if (isDebugStage()) return $tpl_source;

		$tpl_source = preg_replace_callback('/<link[^<>]+href="\/res\/([^"]+)".*>/i', function($matches) {
			return '<?php $_smarty_tpl->smarty->requireRes("css", "' . $matches[1] . '"); ?>';
		}, $tpl_source);
		$tpl_source = preg_replace_callback('/<script[^<>]+src="\/res\/([^"]+)".*(\/>|<\/script>)/i', function($matches) {
			return '<?php $_smarty_tpl->smarty->requireRes("js", "' . $matches[1] . '"); ?>';
		}, $tpl_source);
		return $tpl_source;
	}

	/**
	 * 在模板执行后，把记录下来的 css 和 js 统一插入 html 的适当位置。
	 */
	function outputFilter($tpl_output, Smarty_Internal_Template $template)
	{
		if (!empty($this->linked_res['css'])) {
			$files = implode(',', $this->linked_res['css']);
			$url = $this->prefix . '/res/??' . implode(',', $this->linked_res['css']) . $this->suffix;
			$link = '<link rel="stylesheet" type="text/css" href="' . $url .'">';
			$tpl_output = str_replace('</head>', "{$link}\r\n</head>", $tpl_output);
		}
		if (!empty($this->linked_res['js'])) {
			$files = implode(',', $this->linked_res['js']);
			$url = $this->prefix . '/res/??' . implode(',', $this->linked_res['js']) . $this->suffix;
			$link = '<script type="text/javascript" src="' . $url .'"></script>';
			$tpl_output = str_replace('</body>', "{$link}\r\n</body>", $tpl_output);
		}
		return $tpl_output;
	}

	/**
	 * 声明引入指定的资源文件。
	 * @param string $type 'css' 或者 'js'。
	 * @param string $file 资源文件名，路径相对于资源根目录。
	 */
	public function requireRes($type, $file)
	{
		$this->linked_res[$type][] = $file;
	}
}
